package com.example.patient.service.impl;

import cn.hutool.core.util.IdcardUtil;
import com.example.common.entity.*;
import com.example.common.enums.PayType;
import com.example.common.support.ApiException;
import com.example.common.utils.CheckUtils;
import com.example.common.utils.Kuaidi100Api;
import com.example.common.utils.UIDUtils;
import com.example.patient.dto.req.IMOrderDetailReq;
import com.example.patient.dto.req.IMOrderListReq;
import com.example.patient.dto.req.RxOrderDetailReq;
import com.example.patient.dto.req.RxOrderListReq;
import com.example.patient.dto.resp.IMOrderDetailResp;
import com.example.patient.dto.resp.IMOrderListResp;
import com.example.patient.dto.resp.RxOrderDetailResp;
import com.example.patient.dto.resp.RxOrderListResp;
import com.example.patient.jpa.*;
import com.example.patient.mapper.MyOrderMapper;
import com.example.patient.properties.WxProp;
import com.example.patient.service.MyOrderService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author wxy
 * @Date 2021/1/18 13:54
 * @Version 1.0
 */
@Service
public class MyOrderServiceImpl implements MyOrderService {
    @Resource
    private UIDUtils uidUtils;
    @Resource
    private WxProp wxProp;

    @Resource
    private MyOrderMapper myOrderMapper;

    @Resource
    private OrderMainRepository orderMainRepository;
    @Resource
    private PatientsInfoRepository patientsInfoRepository;
    @Resource
    private ClientPatientsInfoRepository clientPatientsInfoRepository;
    @Resource
    private RxInfoRepository rxInfoRepository;
    @Resource
    private RxDrugsRepository rxDrugsRepository;
    @Resource
    private HospitalRepository hospitalRepository;
    @Resource
    private LogisticsDRepository logisticsDRepository;
    @Resource
    private RxMainRepository rxMainRepository;
    @Resource
    private ClientBaseInfoRepository clientBaseInfoRepository;

    /**
     * 问诊订单
     */
    @Override
    public PageInfo<IMOrderListResp> IMOrderList(IMOrderListReq req) {
        CheckUtils.checkNull(req, new ApiException(1, "对象不能为空"));
        Integer aType = CheckUtils.checkNullReturn(req.getAType(), new ApiException(1, "AType不能为空"));
        Integer pageNumber = CheckUtils.checkNullReturn(req.getPage(), new ApiException(1, "分页页数不能为空"));
        Integer pageSize = CheckUtils.checkNullReturn(req.getLimit(), new ApiException(1, "分页条数不能为空"));
        Long uid = uidUtils.getUid();

        PageInfo<IMOrderListResp> pageInfo = PageHelper.startPage(pageNumber, pageSize).doSelectPageInfo(() -> myOrderMapper.IMOrderList(uid, aType));
        List<IMOrderListResp> list = pageInfo.getList();
        if (!CollectionUtils.isEmpty(list)) {
            list = list.stream()
                    .peek(p -> p.setPayUrl(p.getSystemStatus() == 1L ? String.format(wxProp.getPayUrl(), p.getOrderNo(), "1") : ""))
                    .collect(Collectors.toList());
        }
        pageInfo.setList(list);
        return pageInfo;
    }

    /**
     * 问诊订单 详情
     */
    @Override
    public IMOrderDetailResp IMOrderDetail(IMOrderDetailReq req) {
        CheckUtils.checkNull(req, new ApiException(1, "对象不能为空"));
        String orderNo = CheckUtils.checkNullReturn(req.getOrderNO(), new ApiException(1, "订单id不能为空"));

        OrderMain orderMain = orderMainRepository.findById(orderNo).orElseThrow(() -> new ApiException(1, "未查询到数据"));

        IMOrderDetailResp.DocInfoResp docInfoResp = new IMOrderDetailResp.DocInfoResp();
        Map<String, Object> map = myOrderMapper.IMOrderDetailRespDocInfoResp(orderMain.getDcId());
        if (!CollectionUtils.isEmpty(map)) {
            docInfoResp.setName(null == map.get("Name") ? null : (String) map.get("Name"));
            docInfoResp.setHead(null == map.get("Head") ? null : (String) map.get("Head"));
            docInfoResp.setDepName(null == map.get("depName") ? null : (String) map.get("depName"));
        }

        PatientsInfo patientsInfo = patientsInfoRepository.findById(orderMain.getPatientsInfoID()).orElseThrow(() -> new ApiException(1, "未查询到数据"));
        IMOrderDetailResp.GuardianResp guardianResp = new IMOrderDetailResp.GuardianResp();
        if (6 >= patientsInfo.getAge()) {
            ClientPatientsInfo clientPatientsInfo = clientPatientsInfoRepository.findById(orderMain.getPid()).orElseThrow(() -> new ApiException(1, "未查询到数据"));
            guardianResp.setGuardianName(clientPatientsInfo.getGuardianName());
            guardianResp.setShowIdNo(IdcardUtil.hide(clientPatientsInfo.getGuardianIDNO(), 7, 15));
        }

        IMOrderDetailResp.PatInfoResp patInfoResp = new IMOrderDetailResp.PatInfoResp();
        patInfoResp.setName(patientsInfo.getName());
        patInfoResp.setSex(patientsInfo.getSex());
        patInfoResp.setAge(patientsInfo.getAge());
        patInfoResp.setGuardian(guardianResp);
        patInfoResp.setFirst(patientsInfo.getFirst());
        patInfoResp.setChiefComplaint(patientsInfo.getChiefComplaint());

        IMOrderDetailResp.OrderInfoResp orderInfoResp = new IMOrderDetailResp.OrderInfoResp();
        orderInfoResp.setOrderNo(orderMain.getOrderNo());
        orderInfoResp.setSystemStatus(orderMain.getSystemStatus());
        orderInfoResp.setOcStatus(orderMain.getOcStatus());
        orderInfoResp.setAType(orderMain.getAType());
        orderInfoResp.setCreateTime(orderMain.getCreateTime());
        orderInfoResp.setAskMoney(orderMain.getAskMoney());
        orderInfoResp.setPayType(orderMain.getPayType());
        orderInfoResp.setPayName(PayType.valueToDesc(orderMain.getPayType()));
        String payUrl = null;
        if (orderMain.getSystemStatus() == 1 && orderMain.getPayType() == 2) {
            payUrl = String.format(wxProp.getPayUrl(), orderMain.getOrderNo(), "1");
        }
        orderInfoResp.setPayUrl(payUrl);

        IMOrderDetailResp resp = new IMOrderDetailResp();
        resp.setDocInfo(docInfoResp);
        resp.setOrderInfo(orderInfoResp);
        resp.setPatInfo(patInfoResp);
        return resp;
    }

    /**
     * 处方订单
     */
    @Override
    public PageInfo<RxOrderListResp> RxOrderList(RxOrderListReq req) {
        CheckUtils.checkNull(req, new ApiException(1, "对象不能为空"));
        Integer orderStatus = CheckUtils.checkNullReturn(req.getOrderStatus(), new ApiException(1, "订单状态不能为空"));
        Integer pageNumber = CheckUtils.checkNullReturn(req.getPage(), new ApiException(1, "分页页数不能为空"));
        Integer pageSize = CheckUtils.checkNullReturn(req.getLimit(), new ApiException(1, "分页条数不能为空"));
        Long uid = uidUtils.getUid();

        PageInfo<RxOrderListResp> pageInfo = PageHelper.startPage(pageNumber, pageSize).doSelectPageInfo(() -> myOrderMapper.RxOrderList(uid, orderStatus));
        List<RxOrderListResp> list = pageInfo.getList();
        if (!CollectionUtils.isEmpty(list)) {

            List<String> rxOrderNoList = list.stream().map(RxOrderListResp::getRxOrderNo).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(rxOrderNoList)) {
                return pageInfo;
            }

            List<RxOrderListResp.RxInfoResp> zDrugList = rxInfoRepository.findByDrugType(rxOrderNoList)
                    .stream()
                    .map(m -> {
                        RxOrderListResp.RxInfoResp rxInfoResp = new RxOrderListResp.RxInfoResp();
                        rxInfoResp.setRxOrderNo(m.getRxOrderNo());
                        rxInfoResp.setDrugInfo(m.getDrugInfo());
                        return rxInfoResp;
                    })
                    .collect(Collectors.toList());

            List<RxOrderListResp.RxDrugsResp> xDrugList = rxDrugsRepository.findByType(rxOrderNoList)
                    .stream()
                    .map(m -> {
                        RxOrderListResp.RxDrugsResp rxDrugsResp = new RxOrderListResp.RxDrugsResp();
                        rxDrugsResp.setRxOrderNo(m.getRxOrderNo());
                        rxDrugsResp.setDrugName(m.getDrugName());
                        return rxDrugsResp;
                    })
                    .collect(Collectors.toList());

            Hospital hospital = hospitalRepository.findFirstByOrderByIdDesc();
            CheckUtils.checkNull(hospital, new ApiException(1, "未查询到数据"));

            List<String> logisticsOrder = new ArrayList<>();
            List<LogisticsD> logisticsDList = new ArrayList<>();
            // 已提交但未支付成功的订单，直接调支付
            if (orderStatus == 2 || orderStatus == 3) {
                logisticsDList = logisticsDRepository.findByOrderType(rxOrderNoList)
                        .stream()
                        .collect(Collectors.toList());
                if (orderStatus == 2 && !CollectionUtils.isEmpty(logisticsDList)) {
                    logisticsOrder = logisticsDList.stream().map(LogisticsD::getOrderNo).collect(Collectors.toList());
                }
            }

            List<String> finalLogisticsOrder = logisticsOrder;
            List<LogisticsD> finalLogisticsDList = logisticsDList;

            list = list.stream().peek(p -> {
                String drugName;
                if (p.getDType() == 1) {
                    RxOrderListResp.RxInfoResp rxInfoResp = zDrugList.stream().filter(f -> f.getRxOrderNo().equals(p.getRxOrderNo())).findFirst().orElse(null);
                    drugName = null == rxInfoResp ? null : rxInfoResp.getDrugInfo();
                } else {
                    drugName = xDrugList.stream().filter(f -> f.getRxOrderNo().equals(p.getRxOrderNo())).map(RxOrderListResp.RxDrugsResp::getDrugName).collect(Collectors.joining("/"));
                }
                String payUrl = null;
                if (orderStatus == 2 && !CollectionUtils.isEmpty(finalLogisticsOrder) && finalLogisticsOrder.contains(p.getRxOrderNo()) && p.getPayType() == 2) {
                    payUrl = String.format(wxProp.getPayUrl(), p.getRxOrderNo(), "2");
                }
                Integer orderLType = 0;
                if (orderStatus == 3 && !CollectionUtils.isEmpty(finalLogisticsDList) && finalLogisticsDList.stream().anyMatch(f -> f.getOrderNo().equals(p.getRxOrderNo()))) {
                    LogisticsD logisticsD = finalLogisticsDList.stream().filter(f -> f.getOrderNo().equals(p.getRxOrderNo())).findFirst().orElse(null);
                    orderLType = null == logisticsD ? null : logisticsD.getLType();
                }
                p.setHName(hospital.getName());
                p.setDrugName(drugName);
                p.setPayUrl(payUrl);
                p.setOrderLType(orderLType);
            }).collect(Collectors.toList());
        }
        pageInfo.setList(list);
        return pageInfo;
    }

    /**
     * 处方订单 详情
     */
    @Override
    public RxOrderDetailResp RxOrderDetail(RxOrderDetailReq req) {
        CheckUtils.checkNull(req, new ApiException(1, "对象不能为空"));
        Integer orderStatus = CheckUtils.checkNullReturn(req.getOrderStatus(), new ApiException(1, "订单状态不能为空"));
        String rxOrderNO = CheckUtils.checkNullReturn(req.getRxOrderNO(), new ApiException(1, "处方订单id不能为空"));
        Long uid = uidUtils.getUid();

        RxOrderListResp data = myOrderMapper.RxOrderDetail(uid, orderStatus, rxOrderNO);

        RxMain rxMain = rxMainRepository.findById(rxOrderNO).orElseThrow(() -> new ApiException(1, "未查询到数据"));

        List<Map<String, Object>> mapList = myOrderMapper.RxOrderSettlementRespDrugListResp(rxOrderNO);
        CheckUtils.checkNull(mapList, new ApiException(1, "未查询到数据"));
        List<RxOrderDetailResp.DrugListResp> drugList = mapList.stream().map(m -> {
            RxOrderDetailResp.DrugListResp resp = new RxOrderDetailResp.DrugListResp();
            resp.setDrugName(null == m.get("DrugName") ? null : (String) m.get("DrugName"));
            resp.setImg(null == m.get("Img") ? null : (String) m.get("Img"));
            resp.setNum(null == m.get("Num") ? null : (Integer) m.get("Num"));
            resp.setPrice(null == m.get("Price") ? null : (BigDecimal) m.get("Price"));
            resp.setSpec(null == m.get("Spec") ? null : (String) m.get("Spec"));
            return resp;
        }).collect(Collectors.toList());


        LogisticsD logisticsD = null;
        RxOrderDetailResp.OrderLogisticsResp orderLogisticsResp = new RxOrderDetailResp.OrderLogisticsResp();
        // 已提交但未支付成功的订单，直接调支付
        if (orderStatus == 2 || orderStatus == 3 || orderStatus == 4) {
            logisticsD = logisticsDRepository.findById(rxOrderNO).orElseThrow(() -> new ApiException(1, "未查询到数据"));
            if (0 == logisticsD.getLType()) {
                Hospital hospital = hospitalRepository.findFirstByOrderByIdDesc();
                orderLogisticsResp.setSelfAddress(hospital.getSelfAddress());
                orderLogisticsResp.setSelfName(hospital.getSelfName());
                orderLogisticsResp.setIco(hospital.getIco());
                orderLogisticsResp.setWaybill(logisticsD.getWaybill());
            } else if (1 == logisticsD.getLType()) {
                orderLogisticsResp.setName(logisticsD.getName());
                orderLogisticsResp.setTel(logisticsD.getTel());
                orderLogisticsResp.setAddress(logisticsD.getAddress());
                orderLogisticsResp.setWaybill(logisticsD.getWaybill());
            } else {
                orderLogisticsResp = null;
            }
        }

        BigDecimal bigDecimal = drugList.stream().map(m -> new BigDecimal(m.getNum()).multiply(m.getPrice())).reduce(BigDecimal::add).orElseThrow(() -> new ApiException(1, "计算错误"));
        String payUrl = null;
        if (orderStatus == 2 && !ObjectUtils.isEmpty(logisticsD) && data.getPayType() == 2) {
            payUrl = String.format(wxProp.getPayUrl(), rxOrderNO, "2");
        }

        RxOrderDetailResp resp = new RxOrderDetailResp();
        resp.setRxOrderNo(data.getRxOrderNo());
        resp.setName(data.getName());
        resp.setSex(data.getSex());
        resp.setDialectical(data.getDialectical());
        resp.setDocName(data.getDocName());
        resp.setTitle(data.getTitle());
        resp.setHead(data.getHead());
        resp.setDepName(data.getDepName());
        resp.setFreight(rxMain.getFreight());
        resp.setSalePrice(rxMain.getSalePrice());
        resp.setProPrice(bigDecimal);
        resp.setDrugList(drugList);
        resp.setPayUrl(payUrl);
        resp.setOrderLType(null != logisticsD ? logisticsD.getLType() : 0);
        resp.setOrderLogistics(orderLogisticsResp);
        resp.setPayTime(orderStatus == 3 || orderStatus == 4 ? rxMain.getOrderPayTime() : null);
        resp.setDType(rxMain.getDType());
        resp.setArriveTime(orderStatus == 4 ? logisticsD.getArriveTime() : null);
        return resp;
    }

    @Override
    public Map<String, Object> OrderWaybill(String OrderNO){
        String jsons = "";
        Map<String,Object> company = new HashMap<>();
        LogisticsD logistics = logisticsDRepository.findById(OrderNO).orElseThrow(() -> new ApiException(1, "订单信息不全"));
        if(logistics.getIsSend() && logistics.getWaybill() != null && !logistics.getWaybill().isEmpty()){
            company.put("company", logistics.getCompany());
            company.put("nu", logistics.getWaybill());
            jsons = Kuaidi100Api.queryWaybill(logistics.getWaybill().trim(),logistics.getCompanyCode().trim(),logistics.getTel().trim());
        }

        Map<String,Object> res = new HashMap<>();
        res.put("jsons", jsons);
        res.put("order", null);
        res.put("company", company);
        
        return res;
    }
    
    @Override
    public String Receipt(String OrderNO){
        Long uid = uidUtils.getUid();
        LogisticsD logistics = logisticsDRepository.findById(OrderNO).orElseThrow(() -> new ApiException(1, "订单信息不全"));
        if(logistics.getIsArrive())
            return "订单已确认收货";

        ClientBaseInfo c = clientBaseInfoRepository.findById(uid).orElseThrow(() -> new ApiException(1, "用户不存在"));
        
        logistics.setIsArrive(true);
        logistics.setArriveTime(new Date());
        logistics.setArriveName(c.getNickName());

        try {
            logisticsDRepository.save(logistics);
            return "";
        } catch (Exception e) {
        }
        return "订单确认收货失败";
    }
}
